// 编写Promise原生，底层执行过程
(function () {
    // 当我的html文件引用这文件，顶替原来的原生的Promise函数跟方法
    // 这里相当于Promise((resolve，reject)=>{
    // console.log('执行器函数调用');
    // })

    function Promise(excutor) {
        console.log("Promise构造函数调用");

        //保存Promise对象的状态 如果没有调用这resolve 或者 reject 这两个回调函数，那么这个Promise的默认状态为Pending  
        this.status = 'pending';
        // 保存这个Promsie这个对象的结果
        this.data = undefined;

        this.callback = []; //储存then里面成功和失败回调函数

        // 缓存这个this指向
        var _this = this;


        // resolve函数，作用是将Promise的状态改变为fulfilled
        function resolve(result) {
            console.log('resolve函数调用');
    
    
            // 判断这个resolve对象的状态
            if (_this.status !== 'pending') { //如果resolve这个回调函数被调用那么这Promsie的状态为成功状态  
                //这里就是相当于Promise正在进行的状态被该变
                return;
            }
    
            // 修改状态为fulilled 为成功状态
            _this.status = 'fulfilled';

            // 修改值接收resolve的传入的参数（不传参数默为undefined）
            _this.data = result;
    

            if (_this.callback.length > 0) { //说明里面有 等待执行的函数
                setTimeout(() => {
                    _this.callback.forEach((item) => {
                        item.resolveCB(result);
                   })
                });

            }
        }

        // rejected函数，作用是将Promise的状态改变为rejected
        function reject(result) {
            console.log('reject函数调用');

            if (_this.data !== 'pending') {
                return;
            }

            _this.status = 'rejected';//修改状态weirejected 失败状态

            _this.data = result; //修改结果


            if (_this.callback.length>0) {
                setTimeout(() => {
                    _this.callback.forEach((item) => {
                        item.resolveCB(result);
                    })
                })
            }
        }

        try {//尝试执行
            //excutor执行器函数 
            excutor(resolve, reject);
        } catch(res) {
            console.log(res);//接收excutor 其中的报错信息
        }
    }



    // 函数的方法我们一般是写在此函数的Prototype原型内部，
    // Promise常用的方法有then catch
    
    // 当然Promise也有静态方法比如：all race
    
    //Promise 的 then 方法
    Promise.prototype.then = (resolveCB, rejectCB) => {//resolveCB, rejectCB 两个回调函数

        // then这个方法放回的是一个新的Promise对象所以，与用到new
        
        // then 有两个回调函数，成功回调函数，失败回调函数
        console.log('then方法');

        var _this = this; //这里的_this 是为了给里面的计时器用（异步）
        //then 方法执行后返回一个新的Promise对象
        //新的Promise对象的状态和结果取决与成功或者失败的回调函数的返回值

        return new Promise(function (resolve, reject)  { 

            // 如果Promise对象的状态为成功状态
            // 执行此函数
            //分第一种情况这个New Promise对象的状态，如果这个Promise的对象的状态为成功状态，可能出现的情况
            if (_this.status === 'fuifilled') {
                setTimeout(() => { //为什么要使用计时器，因为计时器的异步，需要等待同步执行完成，
                    // 再去执行异步，也就是说需要等待Promise的状态发生改变

                    try {
                        var result = resolveCB(_this.data);//先是把成功回调函数的返回值存到result变量里
                        if (result instanceof Promise) {
                            // 如果result是Promis对象,p2的状态和结构会跟随这个result的状态和结果                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                        }
                        resolveCB(_this.date);//执行结果
                    } catch{
                        
                    }
                })
            }
    
            else if (this.status === 'rejected') {
                setTimeout(() => {
                    rejectCB(_this.data);
                })
            }
    
            else {
                // 如果Promise为进行中的状态
                this.callback.push({
                    'resolveCB': resolveCB,
                    'rejected': rejectCB,
                })
            }
        })



    }
    
    //Promsie 的 cath 方法
    Promise.prototype.catch = function () {
        console.log("catch方法");
    }
    
    // Promise 的 “静态” 方法
    // all 方法可以将多个Promise实例对封装成一个新的Promise实例
    // 接收的是一个数组作为参数
    
    //当所有的子Promise都为成功状态，那么这个Promise的状态才为成功状态
    // 如果其中一个子Pormise为失败状态，name这个Promsie的状态为失败状态
    Promise.all = function () {
        console.log('all方法');
    }
    
    // 档其中一个子Promsie为成功状态，那么这个promie的状态就为成功状态
    Promise.race = function () {
        console.log('race方法');
    }


    window.Promise = Promise;
})()//这里的立即执行函数表示的把这个Promise构造函数暴露出去




